package com.msh.artascope.devcloud.service.client;

import com.alibaba.fastjson.JSONObject;
import com.msh.artascope.devcloud.service.util.RestTemplateUtil;
import com.msh.artascope.devcloud.service.wrapper.K8sWrapper.K8sInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

@Slf4j
@Service
public class K8sClient {

  private RestTemplate restTemplate;

  public K8sClient() {
    this.restTemplate = RestTemplateUtil.newNoCheckSslRestTemplate();
  }

  //-----------命名空间------------------------------------

  private static final String NAMESPACE_CREATE_URL_FORMAT = "%s/api/v1/namespaces";
  private static final String NAMESPACE_GET_UPDATE_URL_FORMAT = "%s/api/v1/namespaces/%s";
  private static final String NAMESPACE_DELETE_URL_FORMAT = "%s/api/v1/namespaces/%s";

  //-----------deployment------------------------------------
  private static final String DEPLOYMENT_LIST_URL_FORMAT = "%s/apis/apps/v1/namespaces/%s/deployments?labelSelector=service in (%s)";

  private static final String DEPLOYMENT_CREATE_URL_FORMAT = "%s/apis/apps/v1/namespaces/%s/deployments";
  private static final String DEPLOYMENT_GET_UPDATE_URL_FORMAT = "%s/apis/apps/v1/namespaces/%s/deployments/%s";
  private static final String DEPLOYMENT_DELETE_URL_FORMAT = "%s/apis/apps/v1/namespaces/%s/deployments/%s";

  //-----------pod------------------------------------

  private static final String POD_MARK_GET_URL_FORMAT = "%s/api/v1/namespaces/%s/pods?labelSelector=service in (%s)";
  private static final String POD_GET_UPDATE_DELETE_URL_FORMAT = "%s/api/v1/namespaces/%s/pods/%s";

  private static final String POD_LOG_GET_URL_FORMAT = "%s/api/v1/namespaces/%s/pods/%s/log?container=app&tailLines=%s";

  //-----------副本数------------------------------------

  private static final String SRCAL_GET_UPDATE_URL_FORMAT = "%s/apis/apps/v1/namespaces/%s/deployments/%s/scale";

  //-----------service------------------------------------

  private static final String SERVICE_CREATE_URL_FORMAT = "%s/api/v1/namespaces/%s/services";
  private static final String SERVICE_GET_UPDATE_DELETE_URL_FORMAT = "%s/api/v1/namespaces/%s/services/%s";

  //-----------ingress------------------------------------

  private static final String INGRESS_CREATE_URL_FORMAT = "%s/apis/extensions/v1beta1/namespaces/%s/ingresses";
  private static final String INGRESS_GET_UPDATE_DELETE_URL_FORMAT = "%s/apis/extensions/v1beta1/namespaces/%s/ingresses/%s";

  //-----------configmap------------------------------------

  private static final String CONFIGMAP_CREATE_URL_FORMAT = "%s/api/v1/namespaces/%s/configmaps";

  //-----------istio-gateway------------------------------------

  private static final String ISTIO_GW_CREATE_URL_FORMAT = "%s/apis/networking.istio.io/v1alpha3/namespaces/%s/gateways";
  private static final String ISTIO_GW_GET_UPDATE_DELETE_URL_FORMAT = "%s/apis/networking.istio.io/v1alpha3/namespaces/%s/gateways/%s";

  //-----------istio-VirtualService------------------------------------

  private static final String ISTIO_VS_CREATE_URL_FORMAT = "%s/apis/networking.istio.io/v1alpha3/namespaces/%s/virtualservices";
  private static final String ISTIO_VS_GET_UPDATE_DELETE_URL_FORMAT = "%s/apis/networking.istio.io/v1alpha3/namespaces/%s/virtualservices/%s";

  //-----------istio-DestinationRule------------------------------------

  private static final String ISTIO_DR_CREATE_URL_FORMAT = "%s/apis/networking.istio.io/v1alpha3/namespaces/%s/destinationrules";
  private static final String ISTIO_DR_GET_UPDATE_DELETE_URL_FORMAT = "%s/apis/networking.istio.io/v1alpha3/namespaces/%s/destinationrules/%s";

  /**
   * 创建命名空间
   *
   * @param k8s
   * @return
   */
  public JSONObject createNamespace(K8sInfo k8s, String body) {
    String url = String.format(NAMESPACE_CREATE_URL_FORMAT, k8s.getHostAndPort());
    return restTemplate
        .exchange(url, HttpMethod.POST, buildHttpEntity(k8s, body), JSONObject.class).getBody();
  }

  public JSONObject getNamespace(K8sInfo k8s){
    String url = String
            .format(NAMESPACE_GET_UPDATE_URL_FORMAT, k8s.getHostAndPort(), k8s.getNamespace());
    return restTemplate
            .exchange(url, HttpMethod.GET, buildHttpEntity(k8s), JSONObject.class).getBody();
  }

  /**
   * 删除命名空间
   * @param k8s
   * @return
   */
  public JSONObject deleteNamespace(K8sInfo k8s){
    String url = String.format(NAMESPACE_DELETE_URL_FORMAT, k8s.getHostAndPort(), k8s.getNamespace());
    return restTemplate
        .exchange(url, HttpMethod.DELETE, buildHttpEntity(k8s), JSONObject.class).getBody();
  }

  public JSONObject createConfigMap(K8sInfo k8s, String body){
    String url = String.format(CONFIGMAP_CREATE_URL_FORMAT, k8s.getHostAndPort(), k8s.getNamespace());
    return restTemplate
            .exchange(url, HttpMethod.POST, buildHttpEntity(k8s, body), JSONObject.class).getBody();
  }

  /**
   * 创建deployment
   * @param k8s
   * @param body
   * @return
   */
  public JSONObject createDeployment(K8sInfo k8s, String body){
    String url = String.format(DEPLOYMENT_CREATE_URL_FORMAT, k8s.getHostAndPort(), k8s.getNamespace());
    return restTemplate
        .exchange(url, HttpMethod.POST, buildHttpEntity(k8s, body), JSONObject.class).getBody();
  }

  /**
   * 更新deployment
   * @param k8s
   * @param moduleName
   * @return
   */
  public JSONObject updateDeployment(K8sInfo k8s, String moduleName, String body){
    String url = String.format(DEPLOYMENT_GET_UPDATE_URL_FORMAT, k8s.getHostAndPort(), k8s.getNamespace(), moduleName);
    return restTemplate
        .exchange(url, HttpMethod.PUT, buildHttpEntity(k8s, body), JSONObject.class).getBody();
  }

  /**
   * 获取deployment
   * @param k8s
   * @param moduleName
   * @return
   */
  public JSONObject getDeployment(K8sInfo k8s, String moduleName) {
    String url = String
        .format(DEPLOYMENT_GET_UPDATE_URL_FORMAT, k8s.getHostAndPort(), k8s.getNamespace(),
            moduleName);
    return restTemplate
        .exchange(url, HttpMethod.GET, buildHttpEntity(k8s), JSONObject.class).getBody();
  }

  public JSONObject listDeployment(K8sInfo k8s, String moduleName) {
    String url = String
        .format(DEPLOYMENT_LIST_URL_FORMAT, k8s.getHostAndPort(), k8s.getNamespace(), moduleName);
    return restTemplate
        .exchange(url, HttpMethod.GET, buildHttpEntity(k8s), JSONObject.class).getBody();
  }

  /**
   * 删除deployment
   *
   * @param k8s
   * @param moduleName
   * @return
   */
  public JSONObject deleteDeployment(K8sInfo k8s, String moduleName) {
    String url = String.format(DEPLOYMENT_DELETE_URL_FORMAT, k8s.getHostAndPort(),
        k8s.getNamespace(), moduleName);
    return restTemplate
        .exchange(url, HttpMethod.DELETE, buildHttpEntity(k8s), JSONObject.class).getBody();
  }


  public JSONObject deletePod(K8sInfo k8s, String podName){
    String url = String.format(POD_GET_UPDATE_DELETE_URL_FORMAT, k8s.getHostAndPort(), k8s.getNamespace(), podName);
    return restTemplate
        .exchange(url, HttpMethod.DELETE, buildHttpEntity(k8s), JSONObject.class).getBody();

  }

  /**
   * 获取pods
   * @param k8s
   * @param moduleName
   * @return
   */
  public JSONObject getPods(K8sInfo k8s, String moduleName){
    String url = String.format(POD_MARK_GET_URL_FORMAT, k8s.getHostAndPort(), k8s.getNamespace(), moduleName);
    return restTemplate
        .exchange(url, HttpMethod.GET, buildHttpEntity(k8s), JSONObject.class).getBody();
  }

  public String getLogs(K8sInfo k8s, String podName, Integer line){
    String url = String.format(POD_LOG_GET_URL_FORMAT, k8s.getHostAndPort(), k8s.getNamespace(), podName, line);
    return restTemplate
        .exchange(url, HttpMethod.GET, buildHttpEntity(k8s), String.class).getBody();
  }

  /**
   * 修改副本数
   * @param k8s
   * @param moduleName
   * @return
   */
  public JSONObject getScale(K8sInfo k8s, String moduleName){
//    String url = String.format(SRCAL_GET_UPDATE_URL_FORMAT, k8s.getHostAndPort(), namespace, moduleName);
//    JSONObject jsonObject = restTemplate
//        .exchange(url, HttpMethod.PUT, buildHttpEntity(k8s), JSONObject.class).getBody();
//    String resourceVersion = jsonObject.getJSONObject("metadata").getString("resourceVersion");
//    BizException.doThrowIfNull("未完全处理", jsonObject);
//    return jsonObject;
    String url = String.format(SRCAL_GET_UPDATE_URL_FORMAT, k8s.getHostAndPort(),
        k8s.getNamespace(), moduleName);
    return restTemplate
        .exchange(url, HttpMethod.GET, buildHttpEntity(k8s), JSONObject.class).getBody();
  }

  public JSONObject updateScale(K8sInfo k8s, String deployName, String body) {
    String url = String.format(SRCAL_GET_UPDATE_URL_FORMAT, k8s.getHostAndPort(),
        k8s.getNamespace(), deployName);
    return restTemplate
        .exchange(url, HttpMethod.PUT, buildHttpEntity(k8s, body), JSONObject.class).getBody();
  }


  public JSONObject createService(K8sInfo k8s, String body) {
    String url = String.format(SERVICE_CREATE_URL_FORMAT, k8s.getHostAndPort(), k8s.getNamespace());
    return restTemplate
        .exchange(url, HttpMethod.POST, buildHttpEntity(k8s, body), JSONObject.class).getBody();
  }

  public JSONObject updateService(K8sInfo k8s, String moduleName, String body){
    String url = String.format(SERVICE_GET_UPDATE_DELETE_URL_FORMAT, k8s.getHostAndPort(), k8s.getNamespace(), moduleName);
    return restTemplate
        .exchange(url, HttpMethod.PUT, buildHttpEntity(k8s, body), JSONObject.class).getBody();
  }

  public JSONObject deleteService(K8sInfo k8s, String moduleName){
    String url = String.format(SERVICE_GET_UPDATE_DELETE_URL_FORMAT, k8s.getHostAndPort(), k8s.getNamespace(), moduleName);
    return restTemplate
        .exchange(url, HttpMethod.DELETE, buildHttpEntity(k8s), JSONObject.class).getBody();
  }

  public JSONObject getService(K8sInfo k8s, String moduleName){
    String url = String.format(SERVICE_GET_UPDATE_DELETE_URL_FORMAT, k8s.getHostAndPort(), k8s.getNamespace(), moduleName);
    return restTemplate
        .exchange(url, HttpMethod.GET, buildHttpEntity(k8s), JSONObject.class).getBody();
  }

  public JSONObject createIngress(K8sInfo k8s, String body){
    String url = String.format(INGRESS_CREATE_URL_FORMAT, k8s.getHostAndPort(), k8s.getNamespace());
    return restTemplate
        .exchange(url, HttpMethod.POST, buildHttpEntity(k8s, body), JSONObject.class).getBody();
  }

  public JSONObject updateIngress(K8sInfo k8s, String moduleName, String body){
    String url = String.format(INGRESS_GET_UPDATE_DELETE_URL_FORMAT, k8s.getHostAndPort(), k8s.getNamespace(), moduleName);
    return restTemplate
        .exchange(url, HttpMethod.PUT, buildHttpEntity(k8s, body), JSONObject.class).getBody();
  }

  public JSONObject getIngress(K8sInfo k8s, String moduleName){
    String url = String.format(INGRESS_GET_UPDATE_DELETE_URL_FORMAT, k8s.getHostAndPort(), k8s.getNamespace(), moduleName);
    return restTemplate
        .exchange(url, HttpMethod.GET, buildHttpEntity(k8s), JSONObject.class).getBody();
  }

  public JSONObject deleteIngress(K8sInfo k8s, String moduleName) {
    String url = String.format(INGRESS_GET_UPDATE_DELETE_URL_FORMAT, k8s.getHostAndPort(),
        k8s.getNamespace(), moduleName);
    return restTemplate
        .exchange(url, HttpMethod.DELETE, buildHttpEntity(k8s), JSONObject.class).getBody();
  }

  //-------------------istoio-gw-------------------------------------------------

  public JSONObject createIstioGateway(K8sInfo k8s, String body) {
    return create(k8s, ISTIO_GW_CREATE_URL_FORMAT, body);
  }

  public JSONObject updateIstioGateway(K8sInfo k8s, String gatewayName, String body) {
    return update(k8s, ISTIO_GW_GET_UPDATE_DELETE_URL_FORMAT, gatewayName, body);
  }

  public JSONObject getIstioGateway(K8sInfo k8s, String gatewayName) {
    return get(k8s, ISTIO_GW_GET_UPDATE_DELETE_URL_FORMAT, gatewayName);
  }

  public JSONObject deleteIstioGateway(K8sInfo k8s, String gatewayName) {
    return delete(k8s, ISTIO_GW_GET_UPDATE_DELETE_URL_FORMAT, gatewayName);
  }

  //-------------------istoio-vs-------------------------------------------------

  public JSONObject createIstioVirtualService(K8sInfo k8s, String body) {
    return create(k8s, ISTIO_VS_CREATE_URL_FORMAT, body);
  }

  public JSONObject updateIstioVirtualService(K8sInfo k8s, String gatewayName, String body) {
    return update(k8s, ISTIO_VS_GET_UPDATE_DELETE_URL_FORMAT, gatewayName, body);
  }

  public JSONObject getIstioVirtualService(K8sInfo k8s, String gatewayName) {
    return get(k8s, ISTIO_VS_GET_UPDATE_DELETE_URL_FORMAT, gatewayName);
  }

  public JSONObject deleteIstioVirtualService(K8sInfo k8s, String gatewayName) {
    return delete(k8s, ISTIO_VS_GET_UPDATE_DELETE_URL_FORMAT, gatewayName);
  }

  //-------------------istoio-cr-------------------------------------------------

  public JSONObject createIstioDestinationRule(K8sInfo k8s, String body) {
    return create(k8s, ISTIO_DR_CREATE_URL_FORMAT, body);
  }

  public JSONObject updateIstioDestinationRule(K8sInfo k8s, String gatewayName, String body) {
    return update(k8s, ISTIO_DR_GET_UPDATE_DELETE_URL_FORMAT, gatewayName, body);
  }

  public JSONObject getIstioDestinationRule(K8sInfo k8s, String name) {
    return get(k8s, ISTIO_DR_GET_UPDATE_DELETE_URL_FORMAT, name);
  }

  public JSONObject deleteIstioDestinationRule(K8sInfo k8s, String name) {
    return delete(k8s, ISTIO_DR_GET_UPDATE_DELETE_URL_FORMAT, name);
  }


  public JSONObject create(K8sInfo k8s, String urlFormat, String body) {
    String url = String.format(urlFormat, k8s.getHostAndPort(), k8s.getNamespace());
    return restTemplate
        .exchange(url, HttpMethod.POST, buildHttpEntity(k8s, body), JSONObject.class).getBody();
  }

  public JSONObject update(K8sInfo k8s, String urlFormat, String name, String body) {
    String url = String.format(urlFormat, k8s.getHostAndPort(), k8s.getNamespace(), name);
    return restTemplate
        .exchange(url, HttpMethod.PUT, buildHttpEntity(k8s, body), JSONObject.class).getBody();
  }

  public JSONObject get(K8sInfo k8s, String urlFormat, String name) {
    String url = String
        .format(urlFormat, k8s.getHostAndPort(), k8s.getNamespace(), name);
    return restTemplate
        .exchange(url, HttpMethod.GET, buildHttpEntity(k8s), JSONObject.class).getBody();
  }

  public JSONObject delete(K8sInfo k8s, String urlFormat, String name) {
    String url = String
        .format(urlFormat, k8s.getHostAndPort(), k8s.getNamespace(), name);
    return restTemplate
        .exchange(url, HttpMethod.DELETE, buildHttpEntity(k8s), JSONObject.class).getBody();
  }


  private HttpEntity<String> buildHttpEntity(K8sInfo k8s) {
    return buildHttpEntity(k8s, null);
  }

  private HttpEntity<String> buildHttpEntity(K8sInfo k8s, String body) {
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    if (!StringUtils.isEmpty(k8s.getAuthorization())){
      headers.add("Authorization", k8s.getAuthorization());
    }
    return new HttpEntity<String>(body, headers);
  }

}
